package net.sxnic.workflow.conf;

import java.io.File;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sxnic.comm.utils.CommUtils;
import net.sxnic.item.ItemConstants;
import net.sxnic.ugr.UgrConstant;
import net.sxnic.ugr.context.AppContext;
import net.sxnic.ugr.user.User;
import net.sxnic.ugr.user.UserManager;
import net.sxnic.ugr.utils.UgrManagerUtils;
import net.sxnic.workflow.node.NodeConfig;
import net.sxnic.workflow.task.util.TaskUtils;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoader;

/**
 * 工作流转工具类配置文件实现
 * 
 * @author 孙宇飞
 * 
 */
@SuppressWarnings("unchecked")
public class WfConfigUtilsFileImpl implements WfConfigUtilsInterface {

	private static Logger logger = LoggerFactory
			.getLogger(WfConfigUtilsFileImpl.class);

	public static Document doc;

	public static String config_file_path = ContextLoader.getCurrentWebApplicationContext()
			.getServletContext().getRealPath("/") + "config/"+ItemConstants.SYSTEM_CALALOG_ALIAS+"/wf_config.xml";

	public String findValidateDef(String processName, String nodeName)
			throws Exception {
		Node n = findNodeElement(processName, nodeName).selectSingleNode(
				"validate");

		if (n == null) {
			logger.error("pd={},nodeName={} 在xml文件中没有找到相应“验证”的内容", processName,
					nodeName);
			return "";
		} else {
			return n.getText();
		}
	}

	public String findAssigneeDef(String processName, String nodeName)
			throws Exception {
		Node n = findNodeElement(processName, nodeName).selectSingleNode(
				"assignee");

		if (n == null) {
			logger.error("pd={},nodeName={} 在xml文件中没有找到相应“接收人”的内容",
					processName, nodeName);
			throw new Exception("在mxl中查找“接收人”失败");
		} else {
			return n.getText();
		}
	}

	public Set<String> findNextNodes(String processName, String nodeName)
			throws Exception {
		Node n = findNodeElement(processName, nodeName).selectSingleNode(
				"nextNode");

		if (n == null) {
			logger.info("pd={},nodeName={} 在xml文件中没有找到“后续节点”", processName,
					nodeName);
			return null;
			// throw new Exception("在mxl中查找“后续节点”失败");
		} else {
			String[] nodes = StringUtils.split(n.getText(), ",");
			return CommUtils.ArraytoSet(nodes);
		}
	}

	public String findStartNodeName(String processName) throws Exception {

		if (doc == null) {
			readxml(new File(config_file_path));
		}

		List<Element> nodeList = doc.selectNodes("/root/"+processName);

		if (nodeList == null) {
			logger.error("pd={},在xml文件中没有找到相应的pd", processName);
			throw new Exception("在mxl中查找节点失败");
		}

		Element nodeElement = null;
		nodeList = nodeList.get(0).selectNodes("node");

		for (Element e : nodeList) {
			if ("start".equals(e.attributeValue("cate"))) {
				nodeElement = e;
				break;
			}
		}

		if (nodeElement == null) {
			logger.error("pd={},在xml文件中没有找到相应的pd", processName);
			throw new Exception("在mxl中查找节点失败");
		} else {
			return nodeElement.attributeValue("name");
		}
	}

	public String findJSP(String processName, String nodeName) throws Exception {
		Node n = findNodeElement(processName, nodeName).selectSingleNode("jsp");

		if (n == null) {
			logger.error("pd={},nodeName={} 在xml文件中没有找到相应JSP的内容", processName,
					nodeName);
			throw new Exception("在mxl中查找JSP失败");
		} else {
			return n.getText();
		}
	}

	public static Element findNodeElement(String processName, String nodeName)
			throws Exception {

		if (doc == null) {
			readxml(new File(config_file_path));
		}

		List<Element> nodeList = doc.selectNodes("/root/"+processName);

		if (nodeList == null || nodeList.size()==0) {
			logger.error("pd={},在xml文件中没有找到相应的pd", processName);
			throw new Exception("在mxl中查找节点失败");
		}
		
		Element nodeElement = null;
		nodeList = nodeList.get(0).selectNodes("node");

		for (Element e : nodeList) {
			if (nodeName.equals(e.attributeValue("name"))) {
				nodeElement = e;
				break;
			}
		}

		if (nodeElement == null) {
			logger.error("pd={},在xml文件中没有找到相应的pd", processName);
			throw new Exception("在mxl中查找节点失败");
		} else {
			return nodeElement;
		}
	}

	public Set<String> findHandlers(String processName, String nodeName,
			String action) throws Exception {

		Set<String> set = new LinkedHashSet<String>();

		List<Element> nodeList = findNodeElement(processName, nodeName)
				.selectNodes("handler");

		String handlerClass;
		String handlerAction;

		for (Element en : nodeList) {
			handlerClass = en.attributeValue("class");
			handlerAction = en.attributeValue("action");

			if (StringUtils.isBlank(handlerAction)
					|| StringUtils.isBlank(handlerClass)) {
				throw new Exception("handler的class属性和action属性必须有");
			}

			if (handlerAction.contains(action)) {
				logger.debug("===pd handler===" + handlerClass
						+ "=====actions===" + handlerAction);
				set.add(handlerClass);
			}
		}

		return set;
	}

	public static void readxml(File file) throws Exception {

		SAXReader saxReader = new SAXReader();
		doc = saxReader.read(file);

		logger.debug("read xml file success! file :" + file.getAbsolutePath());

	}

	public String getNextAssigneeByProcessNode(String processName,
			String currNodeName) throws Exception {
		try {
			Set<String> set = this.findNextNodes(processName, currNodeName);

			if (set == null || set.size() == 0) {
				return "";
			}

			Map<String, String[]> map = new LinkedHashMap<String, String[]>();

			for (String nodeName : set) {
				map.put(nodeName,
						getAssigneeArrayByProcessNode(processName, nodeName));
			}

			return TaskUtils.treatMaptoNextAssignees(map);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public String[] getAssigneeArrayByProcessNode(String processName,
			String nodeName) throws Exception {

		UserManager userManager = UgrManagerUtils.getUserManager();

		// 排序-用户名
		Map<String, String> assignee = new LinkedHashMap<String, String>();

		String currUserName = AppContext.getUserName();
		String nextAssignee = this.findAssigneeDef(processName, nodeName);
		
		String before = "";
		String after = "";
		User user = null;

		if (StringUtils.isNotBlank(nextAssignee)) {
			String[] temp = StringUtils.split(nextAssignee,
					TaskUtils.NODE_SEPARATOR);
			for (String t : temp) {
				before = StringUtils.substringBefore(t,
						TaskUtils.NODE_NEXTASSIGNEES_SEPARATOR);
				after = StringUtils.substringAfter(t,
						TaskUtils.NODE_NEXTASSIGNEES_SEPARATOR);

				// 特殊的接收人
				if (before.equals(NodeConfig.NC_SPECIAL)) {
					//
					String[] temp1 = StringUtils.split(after,
							TaskUtils.NEXTASSIGNEES_SEPARATOR);
					for (String t1 : temp1) {
						if (t1.trim().equals(NodeConfig.DEFAULTASSIGNEE_CHUSHI)) {
							// 处室
							return new String[] { NodeConfig.DEFAULTASSIGNEE_CHUSHI };
						} else if (t1.trim().equals(
								NodeConfig.DEFAULTASSIGNEE_CHUANYUE)) {
							// 传阅
							return new String[] { NodeConfig.DEFAULTASSIGNEE_CHUANYUE };
						} else if (t1.trim().equals(
								NodeConfig.DEFAULTASSIGNEE_CHUZHANG)) {
							// 查询当前用户所在处室的 处长
							user = userManager.getChiefByUsername(currUserName);
							// add to assignee set
							assignee.put(UgrConstant.USER_ORDER_MAP.get(user
									.getUsername()), user.getUsername());

						} else if (t1.trim().equals(
								NodeConfig.DEFAULTASSIGNEE_CHUYUAN)) {
							// 当前人员所在处室
							List<User> list = userManager
									.getAllDeptUsersByUsername(currUserName);

							// 遍历所有的处室成员包括处长
							for (User u : list) {
								// add to assignee set
								assignee.put(String.valueOf(u.getUserOrder()),
										u.getUsername());
							}

						} else if (t1.trim().equals(
								NodeConfig.DEFAULTASSIGNEE_DRAFTER)) {
							// 发起人
							return new String[] { NodeConfig.DEFAULTASSIGNEE_DRAFTER};
						}
					}
				} else if ("user".equals(before)) {
					// users
					String[] temp1 = StringUtils.split(after,
							TaskUtils.NEXTASSIGNEES_SEPARATOR);
					// indexs
					for (String t1 : temp1) {
						user = userManager.getUserByUsername(t1);
						// add to assignee set
						assignee.put(String.valueOf(user.getUserOrder()),
								user.getUsername());
					}
				} else if ("role".equals(before)) {
					// roles
					String[] temp1 = StringUtils.split(after,
							TaskUtils.NEXTASSIGNEES_SEPARATOR);
					for (String t1 : temp1) {
						List<User> users = UgrManagerUtils
								.getAuthorizationManager().getUsersInRole(t1);
						for (User u : users) {
							// add to assignee set
							assignee.put(String.valueOf(u.getUserOrder()),
									u.getUsername());
						}
					}
				} else if ("group".equals(before)) {
					// group
					String[] temp1 = StringUtils.split(after,
							TaskUtils.NEXTASSIGNEES_SEPARATOR);

					for (String t1 : temp1) {
						List<User> users = UgrManagerUtils
								.getAuthorizationManager().getUsersInGroup(t1);
						for (User u : users) {
							// add to assignee set
							assignee.put(String.valueOf(u.getUserOrder()),
									u.getUsername());
						}
					}
				}
			}
		}

		if (assignee == null || assignee.size() == 0) {
			return null;
		}

		// 排序
		String[] temp = new String[assignee.size()];
		String[] temp1 = new String[assignee.size()];

		temp = CommUtils.SettoArray(assignee.keySet());
		Arrays.sort(temp);

		int i = 0;
		for (String ss : temp) {
			temp1[i] = assignee.get(ss);
			i++;
		}

		return temp1;
	}

}
